package cn.mapway.tools.rpc.model;

import com.github.javaparser.ast.type.Type;
import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration;
import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
import com.github.javaparser.resolution.types.ResolvedReferenceType;
import com.github.javaparser.resolution.types.ResolvedType;
import com.github.javaparser.utils.Pair;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Optional;

/**
 * TypeUtil
 * 全局上线问中保存如下信息
 * [type full path name]
 * [field 1]
 * [field 2]
 *
 * @author zhangjianshe@gmail.com
 */
@Slf4j
public class TypeUtil {

    public static Boolean isPrimitive(String type) {
        return Types.contains(type);
    }


    public static void main(String[] args) {
        String type = ".Integer";
        System.out.println(Types.simpleType(type));
        System.out.println(isPrimitive(type));
    }

    /**
     * 解析一个类型，将其解析到 全局exportContext中
     * 并返回这个类型的全名称 cn.mapway.tall.Special
     * 参数的实际类型 放入 actualTypeParameters
     *
     * @param returnType dd
     * @param paraDescription s
     */
    public static void parseType(ApiParaDescription paraDescription, Type returnType) {
        // Type 包括两部分内容
        // 1.类型定义信息
        // 2.实际的类型参数信息
        //
        String typeName = returnType.asString();
        if (isPrimitive(typeName)) {
            //基本类型我们不进行解析,直接放入描述中
            if (paraDescription != null) {
                paraDescription.setTypeName(typeName);
                paraDescription.setSimpleName(Types.simpleType(typeName));
                paraDescription.setIsPrimary(true);
            }
            return;
        }
        log.info("parse Type {} [{}]", returnType.asString(), returnType.getClass().getName());
        //解析类型内容
        ResolvedType resolvedType = returnType.resolve();
        if (resolvedType == null) {
            log.warn("sorry ! I canot find the {} defination", returnType.asString());
            return;
        }
        log.info("parse Type resolved {} [{}]", resolvedType.describe(), resolvedType.getClass().getName());

        if (resolvedType.isReferenceType()) {
            ResolvedReferenceType resolvedReferenceType = resolvedType.asReferenceType();
            //解析出是一个引用类型的定义
            ClassDefination classDefination = parseTypeDefination(resolvedType);

            List<Pair<ResolvedTypeParameterDeclaration, ResolvedType>> typeParametersMap = resolvedReferenceType.getTypeParametersMap();
            log.info("处理类型定义{}", resolvedReferenceType.getQualifiedName());
            for (Pair<ResolvedTypeParameterDeclaration, ResolvedType> t : typeParametersMap) {
                //处理实际参数 分析模板的具体类型
                parseTypeDefination(t.b);
                paraDescription.getTemplateParameters().put(t.a.getQualifiedName(), t.b.describe());
            }
        } else {
            log.warn("我们还没有处理此种类型{}", returnType.asString());
        }

//
//        String fullTypeName=resolvedReferenceType.getQualifiedName();
//        if (!ExportContext.get().hasParsed(fullTypeName)) {
//            //没有解析过
//            ClassDefination classDefination=ExportContext.get().sureClassDefination(fullTypeName);
//            classDefination.setTypeName(fullTypeName);
//            //类型的形式参数
//            resolvedReferenceType.getTypeParametersMap();
//            //字段信息
//
//        }
//
//        //已经解析过了，
//        //解析完类型定义后，我们将参数的实际类型填充的 参数描述表中
//        paraDescription.setTypeName(fullTypeName);
//        paraDescription.setSimpleName(Types.simpleType(fullTypeName));


    }

    /**
     * 处理类型定义，将类型定义信息放入ExportContext中
     *
     * @param resolvedType d
     * @return fdsf
     */
    public static ClassDefination parseTypeDefination(ResolvedType resolvedType) {
        if (resolvedType.isPrimitive()) {
            //基本数据类型 不放入全局对象中

        } else if (resolvedType.isReferenceType()) {
            ResolvedReferenceType resolvedReferenceType = resolvedType.asReferenceType();
            String fullTypeName = resolvedReferenceType.getQualifiedName();
            if (ExportContext.get().hasParsed(fullTypeName)) {
                return ExportContext.get().sureClassDefination(fullTypeName);
            }
            ClassDefination classDefination = ExportContext.get().sureClassDefination(fullTypeName);
            classDefination.setTypeName(fullTypeName);
            Optional<ResolvedReferenceTypeDeclaration> typeDeclaration = resolvedReferenceType.getTypeDeclaration();
            if (typeDeclaration.isPresent()) {

                log.warn("类型定义{}", resolvedReferenceType.getQualifiedName());
                ResolvedReferenceTypeDeclaration resolvedReferenceTypeDeclaration = typeDeclaration.get();
                List<ResolvedTypeParameterDeclaration> typeParameters = resolvedReferenceTypeDeclaration.getTypeParameters();
                for (ResolvedTypeParameterDeclaration rtpd : typeParameters) {
                    classDefination.typeParameters.add(rtpd.getName());
                }
                List<ResolvedFieldDeclaration> allFields = resolvedReferenceTypeDeclaration.getAllFields();
                for (ResolvedFieldDeclaration fieldDeclaration : allFields) {
                    FieldDefination fd = new FieldDefination(fieldDeclaration.getType().describe(), fieldDeclaration.getName());
                    fd.isStatic = fieldDeclaration.isStatic();
                    classDefination.getFields().add(fd);
                    parseTypeDefination(fieldDeclaration.getType());
                }
            } else {
                log.warn("没有找到类型定义信息{}", resolvedReferenceType.getQualifiedName());
            }
            //类型定义
            return classDefination;
        } else {
            log.warn("处理类型定义，暂时还没有解决{}", resolvedType.describe());
        }
        return null;
    }

}
